﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Text.RegularExpressions;

namespace Founder.PKURG.VisioReader
{
    public class VisioXMLReader
    {
        public static List<EntityInfo> GetEntites(string xmlPath)
        {
            List<EntityInfo> infos = new List<EntityInfo>();

            List<PropInfo> attrInfos = new List<PropInfo>();

            XmlDocument doc = new XmlDocument();
            doc.Load(xmlPath);

            XmlNodeList attrNodes = doc.SelectNodes("VisioModels/LogicalModels/LogicalModel/Attributes/Attribute");
            foreach (XmlNode item in attrNodes)
            {
                attrInfos.Add(new PropInfo()
                {
                    AttributeID = item.Attributes["AttributeID"].Value,
                    ConceptualName = item.Attributes["ConceptualName"].Value,
                    Datatype = GetDataType(item.Attributes["PhysicalDatatype"].Value),
                    PhysicalName = item.Attributes["PhysicalName"].Value
                });
            }

            XmlNodeList relationNodes = doc.SelectNodes("VisioModels/LogicalModels/LogicalModel/Relationships/Relationship");
            foreach (XmlNode item in relationNodes)
            {
                string firstNodeId = item.ChildNodes[0].FirstChild.Attributes["FirstAttributeID"].Value;
                string secondNodeId = item.ChildNodes[1].FirstChild.Attributes["SecondAttributeID"].Value;

                attrInfos.Find(x => x.AttributeID == firstNodeId).ForeignKeyInfo = new ForeignInfo()
                {
                    Info = attrInfos.Find(x => x.AttributeID == secondNodeId),
                    IsForeign = true
                };
            }

            XmlNodeList infoNodes = doc.SelectNodes("VisioModels/LogicalModels/LogicalModel/Entities/Entity");
            foreach (XmlNode item in infoNodes)
            {
                infos.Add(new EntityInfo()
                {
                    EntityID = item.Attributes["EntityID"].Value,
                    ConceptualName = item.Attributes["ConceptualName"].Value,
                    PropList = GetPropList(item, attrInfos),
                    PhysicalName = item.Attributes["PhysicalName"].Value
                });
            }

            foreach (EntityInfo item in infos)
            {
                item.PropList.ForEach(x => x.BelongInfo = item);
            }

            return infos;
        }

        private static List<PropInfo> GetPropList(XmlNode node, List<PropInfo> attrInfos)
        {
            List<PropInfo> entityAttrs = new List<PropInfo>();
            XmlNodeList infoNodes = node.SelectNodes("EntityAttributes/EntityAttribute");
            foreach (XmlNode item in infoNodes)
            {
                string value = item.Attributes["EntityAttributeID"].Value;
                entityAttrs.Add(attrInfos.Find(x => x.AttributeID == value));
            }
            return entityAttrs;
        }

        private static PhysicalDatatype GetDataType(string typeString)
        {
            PhysicalDatatype dataType = PhysicalDatatype._VARCHAR;
            Match match = Regex.Match(typeString, "(?<value>[a-z A-Z]*)\\(?", RegexOptions.IgnoreCase);
            if (match.Success)
            {
                //(PhysicalDatatype)("_" + match.Groups["value"].Value);
                Enum.TryParse<PhysicalDatatype>("_" + match.Groups["value"].Value, out dataType);
            }
            return dataType;
        }
    }
}
